package top.liubaiblog.blog.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.liubaiblog.blog.constant.RabbitConstants;
import top.liubaiblog.blog.constant.TokenConstants;
import top.liubaiblog.blog.enumeration.EmailTypeEnums;
import top.liubaiblog.blog.message.EmailMessage;
import top.liubaiblog.blog.pojo.SysUser;
import top.liubaiblog.blog.properties.CodeEmailProperties;
import top.liubaiblog.blog.service.EmailService;
import top.liubaiblog.blog.service.SysUserService;
import top.liubaiblog.blog.util.RedisUtils;

import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

/**
 * @author 留白
 * @description
 */
@Slf4j
@Service
public class EmailServiceImpl implements EmailService {

    //注入邮件工具类
    @Autowired
    @SuppressWarnings("all")
    private JavaMailSender javaMailSender;

    @Autowired
    private SysUserService userService;

    @Autowired
    private CodeEmailProperties codeEmailProperties;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    @SuppressWarnings("all")
    private RabbitTemplate rabbitTemplate;

    // 获取用户名
    @Value("${spring.mail.username}")
    private String sendMailer;

    @Override
    public void send(EmailMessage emailMessage) {
        if (Objects.equals(EmailTypeEnums.HTMl.getName(), emailMessage.getType())) {
            sendHtmlMail(emailMessage);
        } else {
            sendSimpleMail(emailMessage);
        }
    }

    public String loginSendCode(String account) {
        // 安全性校验
        if (!StringUtils.hasText(account)) {
            return "";
        }
        // 获取这个用户的用户名
        SysUser user = userService.getByAccount(account);
        if (Objects.isNull(user)) {
            return "";
        }
        String emailAddr = user.getEmail();
        String tempToken = sendAfterBuildToken(emailAddr, "登录");
        // 返回临时token
        return tempToken;
    }

    public String registerSendCode(String emailAddr) {
        // 安全性校验
        if (!StringUtils.hasText(emailAddr)) {
            return "";
        }
        // 判断邮箱地址是否在数据库中已存在
        boolean exist = userService.isExist(emailAddr);
        if (exist) {
            return "";
        }
        // 发送邮件
        String tempToken = sendAfterBuildToken(emailAddr, "注册");
        // 返回临时token
        return tempToken;
    }

    /**
     * 根据邮箱发送验证码，之后构建个临时令牌返回
     *
     * @param emailAddr 邮箱地址
     * @param operate   操作类型
     * @return 临时令牌
     */
    private String sendAfterBuildToken(String emailAddr, String operate) {
        // 封装邮件信息
        EmailMessage message = new EmailMessage();
        // 生成验证码，发送给个人用户
        String code = UUID.randomUUID().toString().substring(0, 6);
        String text = codeEmailProperties.getText()
                .replace("${code}", code)
                .replace("${operate}", operate);
        message.setSendTo(emailAddr);
        message.setSubject(codeEmailProperties.getSubject());
        message.setText(text);
        message.setType(codeEmailProperties.getType());
        // 异步发送邮件信息
        rabbitTemplate.convertAndSend(RabbitConstants.EMAIL_EXCHANGE,
                RabbitConstants.EMAIL_EXCHANGE_BINDING_QUEUE,
                message);
        // 构建临时token
        String tempToken = UUID.randomUUID().toString();
        // 将验证码保存到redis中
        redisUtils.valSet(TokenConstants.TEMP_PREFIX +
                        TokenConstants.TOKEN_PREFIX +
                        emailAddr + ":" + tempToken,
                code,
                TokenConstants.TEMP_TOKEN_EXPIRATION,
                TokenConstants.TEMP_TOKEN_TIMEUNIT);
        // 返回临时token
        return tempToken;
    }

    /**
     * 发送简单邮件
     */
    private void sendSimpleMail(EmailMessage emailMessage) {
        SimpleMailMessage message = new SimpleMailMessage();
        //邮件发件人
        message.setFrom(sendMailer);
        //邮件收件人 1或多个
        message.setTo(emailMessage.getSendTo().split(","));
        //邮件主题
        message.setSubject(emailMessage.getSubject());
        //邮件内容
        message.setText(emailMessage.getText());
        //邮件发送时间
        message.setSentDate(new Date());
        try {
            javaMailSender.send(message);
            log.info("发送txt邮件成功: {} -> {} ", sendMailer, emailMessage.getSendTo());
        } catch (Exception e) {
            log.error("发送邮件时发生异常！", e);
        }
    }

    /**
     * 发送HTML邮件
     */
    private void sendHtmlMail(EmailMessage emailMessage) {
        MimeMessage message = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //邮件发件人
            helper.setFrom(sendMailer);
            //邮件收件人 1或多个
            helper.setTo(emailMessage.getSendTo().split(","));
            //邮件主题
            helper.setSubject(emailMessage.getSubject());
            //邮件内容
            helper.setText(emailMessage.getText(), true);
            //邮件发送时间
            helper.setSentDate(new Date());
            // 发送附件
            String filePath = emailMessage.getFilePath();
            if (StringUtils.hasText(filePath)) {
                FileSystemResource file = new FileSystemResource(new File(filePath));
                String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
                helper.addAttachment(fileName, file);
            }
            javaMailSender.send(message);
            log.info("发送html邮件成功:{} -> {}", sendMailer, emailMessage.getSendTo());
        } catch (Exception e) {
            log.error("发送邮件时发生异常！", e);
        }
    }
}
